# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: helpers\status_cache\scan_job_status_cache_base.py
import logging
from sqlalchemy import select as sql_select
from db import Connection
from db.tables.scan_session_jobs import ScanSessionJobsTable, ScanSessionJobRow

__logger = logging.getLogger("helpers.status_cache")


class ScanJobStatusCache:
    def __init__(self, max_vuln_backlog=5, max_message_backlog=10):
        self.max_vuln_backlog = max_vuln_backlog
        self.max_message_backlog = max_message_backlog

    @staticmethod
    def _get_entry_from_jobs_table(shard, scanning_app, scan_session_id):
        entry = None
        with Connection(shard) as (db):
            q = (
                sql_select((ScanSessionJobRow.stats,))
                .where(ScanSessionJobRow.scan_session_id == scan_session_id)
                .where(ScanSessionJobRow.scanning_app == scanning_app)
            )
            row = db.execute(q).fetchone()
            if row:
                if row.stats:
                    entry = row.stats
        return entry

    @staticmethod
    def _populate_entry(entry):
        if entry is None:
            entry = dict(main={}, hosts={})
        if "messages" not in entry["main"]:
            entry["main"]["messages"] = []
        if "vulns" not in entry["main"]:
            entry["main"]["vulns"] = []
        if "progress" not in entry["main"]:
            entry["main"]["progress"] = 0
        return entry

    @staticmethod
    def _save_entry_to_json_table(
        shard, scanning_app, scan_session_id, entry, merge=False
    ):
        with Connection(shard) as (db):
            if merge:
                pass
            q = (
                (ScanSessionJobsTable.update(values=dict(stats=entry)))
                .where(ScanSessionJobRow.scan_session_id == scan_session_id)
                .where(ScanSessionJobRow.scanning_app == scanning_app)
            )
            db.execute(q)

    @staticmethod
    def _merge_in_main_keys(entry, new_data):
        for key in new_data:
            if key == "main":
                entry["main"] = {}
            else:
                if key == "progress":
                    if new_data.get("status") == "finished":
                        pass
            if new_data["progress"] is not None:
                entry["main"]["progress"] = new_data["progress"]
            else:
                if key == "web_scan_status":
                    if new_data["web_scan_status"]:
                        if "web_scan_status" not in entry["main"]:
                            entry["main"]["web_scan_status"] = dict()
                        for k in new_data["web_scan_status"]:
                            entry["main"]["web_scan_status"][k] = new_data[
                                "web_scan_status"
                            ][k]

                    if key == "status":
                        entry["main"]["status"] = new_data["status"]
                        if new_data["status"] == "finished":
                            entry["main"]["progress"] = 100
            if "duration" in new_data:
                entry["main"]["duration"] = new_data["duration"]

    @staticmethod
    def _merge_in_sub_target_keys(entry, target_id, host, is_starting_host, new_data):
        if "hosts" not in entry:
            entry["hosts"] = {}
        if target_id not in entry["hosts"]:
            entry["hosts"][target_id] = dict(
                host=host, is_starting_host=is_starting_host
            )
        for key in new_data:
            if key == "web_scan_status":
                if "web_scan_status" not in entry["hosts"][target_id]:
                    entry["hosts"][target_id]["web_scan_status"] = dict()
                for k in new_data["web_scan_status"]:
                    entry["hosts"][target_id]["web_scan_status"][k] = new_data[
                        "web_scan_status"
                    ][k]

            elif key == "target_info":
                if "target_info" not in entry["hosts"][target_id]:
                    entry["hosts"][target_id]["target_info"] = dict()
                if new_data["target_info"]:
                    for k in new_data["target_info"]:
                        entry["hosts"][target_id]["target_info"][k] = new_data[
                            "target_info"
                        ][k]

            elif key == "aborted_reason":
                entry["hosts"][target_id]["aborted_reason"] = new_data["aborted_reason"]
            elif key == "aborted":
                entry["hosts"][target_id]["aborted"] = new_data["aborted"]
            elif key == "external_hosts":
                if "external_hosts" not in entry["hosts"][target_id]:
                    entry["hosts"][target_id]["external_hosts"] = []
                for v in new_data["external_hosts"]:
                    if v not in entry["hosts"][target_id]["external_hosts"]:
                        entry["hosts"][target_id]["external_hosts"].append(v)

    def get_entry(self, shard, scanning_app, scan_session_id, enable_db_lookup=True):
        raise NotImplementedError()

    def del_entry(self, shard, scanning_app, scan_session_id):
        raise NotImplementedError()

    def update_main_keys(self, shard, scanning_app, scan_session_id, new_data):
        raise NotImplementedError()

    def update_sub_target_keys(
        self,
        shard,
        scanning_app,
        scan_session_id,
        target_id,
        host,
        is_starting_host,
        new_data,
    ):
        """
        :param is_starting_host:
        :param shard:
        :param scanning_app:
        :param scan_session_id:
        :param target_id:
        :param host:
        :param new_data:  is_starting_host=False, web_scan_status=None, target_info=None, aborted=None,
                          aborted_reason=None, external_hosts=None
        :return:
        """
        raise NotImplementedError()

    def add_message(
        self,
        shard,
        scanning_app,
        scan_session_id,
        kind,
        level,
        data=None,
        target_info=None,
    ):
        raise NotImplementedError()

    def add_vuln(
        self,
        shard,
        scanning_app,
        scan_session_id,
        vuln_name,
        vuln_id,
        severity,
        target_info,
    ):
        raise NotImplementedError()

    def save_entry(self, shard, scanning_app, scan_session_id, merge=False):
        raise NotImplementedError()

    def save_all(self, shard, merge=False, empty_cache=True):
        raise NotImplementedError()
